home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / desc.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  21KB  |  828 lines

  1. /*
  2.  * desc.c: handle object descriptions, mostly string handling code 
  3.  *
  4.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  5.  *
  6.  * This software may be copied and distributed for educational, research, and
  7.  * not for profit purposes provided that this copyright and statement are
  8.  * included in all such copies. 
  9.  */
  10.  
  11. #include "constant.h"
  12. #include "config.h"
  13. #include "types.h"
  14. #include "externs.h"
  15.  
  16. #ifdef USG
  17. #ifndef ATARIST_MWC
  18. #include <string.h>
  19. #endif
  20. #else
  21. #include <strings.h>
  22. #endif
  23.  
  24. /* Lets do all prototypes correctly.... -CWS */
  25. #ifndef NO_LINT_ARGS
  26. #ifdef __STDC__
  27. static void unsample(inven_type *);
  28. #else
  29. static void unsample();
  30. #endif
  31. #endif
  32.  
  33. char                titles[MAX_TITLES][10];
  34.  
  35. /* Object descriptor routines                     */
  36.  
  37. int 
  38. is_a_vowel(ch)
  39. int ch;
  40. {
  41.     switch (ch & 127) {
  42.       case 'a':
  43.       case 'e':
  44.       case 'i':
  45.       case 'o':
  46.       case 'u':
  47.       case 'A':
  48.       case 'E':
  49.       case 'I':
  50.       case 'O':
  51.       case 'U':
  52.     return (TRUE);
  53.       default:
  54.     return (FALSE);
  55.     }
  56. }
  57.  
  58. /* Initialize all Potions, wands, staves, scrolls, etc.     */
  59. void 
  60. magic_init()
  61. {
  62.     register int         h, i, j, k;
  63.     register const char *tmp;
  64.     vtype                string;
  65.  
  66.     set_seed(randes_seed);
  67.  
  68. /* The first 3 entries for colors are fixed, (slime & apple juice, water) */
  69.     for (i = 3; i < MAX_COLORS; i++) {
  70.     j = randint(MAX_COLORS - 3) + 2;
  71.     tmp = colors[i];
  72.     colors[i] = colors[j];
  73.     colors[j] = tmp;
  74.     }
  75.     for (i = 0; i < MAX_WOODS; i++) {
  76.     j = randint(MAX_WOODS) - 1;
  77.     tmp = woods[i];
  78.     woods[i] = woods[j];
  79.     woods[j] = tmp;
  80.     }
  81.     for (i = 0; i < MAX_METALS; i++) {
  82.     j = randint(MAX_METALS) - 1;
  83.     tmp = metals[i];
  84.     metals[i] = metals[j];
  85.     metals[j] = tmp;
  86.     }
  87.     for (i = 0; i < MAX_ROCKS; i++) {
  88.     j = randint(MAX_ROCKS) - 1;
  89.     tmp = rocks[i];
  90.     rocks[i] = rocks[j];
  91.     rocks[j] = tmp;
  92.     }
  93.     for (i = 0; i < MAX_AMULETS; i++) {
  94.     j = randint(MAX_AMULETS) - 1;
  95.     tmp = amulets[i];
  96.     amulets[i] = amulets[j];
  97.     amulets[j] = tmp;
  98.     }
  99.     for (i = 0; i < MAX_MUSH; i++) {
  100.     j = randint(MAX_MUSH) - 1;
  101.     tmp = mushrooms[i];
  102.     mushrooms[i] = mushrooms[j];
  103.     mushrooms[j] = tmp;
  104.     }
  105.     for (h = 0; h < MAX_TITLES; h++) {
  106.     string[0] = '\0';
  107.     k = randint(2) + 1;
  108.     for (i = 0; i < k; i++) {
  109.         for (j = randint(2); j > 0; j--)
  110.         (void)strcat(string, syllables[randint(MAX_SYLLABLES) - 1]);
  111.         if (i < k - 1)
  112.         (void)strcat(string, " ");
  113.     }
  114.     if (string[8] == ' ')
  115.         string[8] = '\0';
  116.     else
  117.         string[9] = '\0';
  118.     (void)strcpy(titles[h], string);
  119.     }
  120.     reset_seed();
  121. }
  122.  
  123. int16 
  124. object_offset(t_ptr)
  125. inven_type *t_ptr;
  126. {
  127.     switch (t_ptr->tval) {
  128.       case TV_ROD:
  129.     return (7);           /* -CFT */
  130.       case TV_AMULET:
  131.     return (0);
  132.       case TV_RING:
  133.     return (1);
  134.       case TV_STAFF:
  135.     return (2);
  136.       case TV_WAND:
  137.     return (3);
  138.       case TV_SCROLL1:
  139.       case TV_SCROLL2:
  140.     return (4);
  141.       case TV_POTION1:
  142.       case TV_POTION2:
  143.     return (5);
  144.       case TV_FOOD:
  145.     if ((t_ptr->subval & (ITEM_SINGLE_STACK_MIN - 1)) < MAX_MUSH)
  146.         return (6);
  147.     return (-1);
  148.       default:
  149.     return (-1);
  150.     }
  151. }
  152.  
  153. /* Remove "Secret" symbol for identity of object             */
  154. void 
  155. known1(i_ptr)
  156. inven_type *i_ptr;
  157. {
  158.     int16 offset;
  159.     int8u indexx;
  160.  
  161.     if ((offset = object_offset(i_ptr)) < 0)
  162.     return;
  163.     offset <<= 6;
  164.     indexx = i_ptr->subval & (ITEM_SINGLE_STACK_MIN - 1);
  165.     object_ident[offset + indexx] |= OD_KNOWN1;
  166. /* clear the tried flag, since it is now known */
  167.     object_ident[offset + indexx] &= ~OD_TRIED;
  168. }
  169.  
  170. int 
  171. known1_p(i_ptr)
  172. inven_type *i_ptr;
  173. {
  174.     int16 offset;
  175.     int8u indexx;
  176.  
  177. /* Items which don't have a 'color' are always known1, so that they can be
  178.  * carried in order in the inventory.  
  179.  */
  180.     if ((offset = object_offset(i_ptr)) < 0)
  181.     return OD_KNOWN1;
  182.     if (store_bought_p(i_ptr))
  183.     return OD_KNOWN1;
  184.     offset <<= 6;
  185.     indexx = i_ptr->subval & (ITEM_SINGLE_STACK_MIN - 1);
  186.     return (object_ident[offset + indexx] & OD_KNOWN1);
  187. }
  188.  
  189.  
  190. /* Remove "Secret" symbol for identity of plusses             */
  191. void 
  192. known2(i_ptr)
  193. inven_type *i_ptr;
  194. {
  195.     unsample(i_ptr);
  196.     i_ptr->ident |= ID_KNOWN2;
  197. }
  198.  
  199.  
  200. int 
  201. known2_p(i_ptr)
  202. inven_type *i_ptr;
  203. {
  204.     return (i_ptr->ident & ID_KNOWN2);
  205. }
  206.  
  207.  
  208. void 
  209. clear_known2(i_ptr)
  210. inven_type *i_ptr;
  211. {
  212.     i_ptr->ident &= ~ID_KNOWN2;
  213. }
  214.  
  215.  
  216. void 
  217. clear_empty(i_ptr)
  218. inven_type *i_ptr;
  219. {
  220.     i_ptr->ident &= ~ID_EMPTY;
  221. }
  222.  
  223. void 
  224. store_bought(i_ptr)
  225. inven_type *i_ptr;
  226. {
  227.     i_ptr->ident |= ID_STOREBOUGHT;
  228.     known2(i_ptr);
  229. }
  230.  
  231.  
  232. int 
  233. store_bought_p(i_ptr)
  234. inven_type *i_ptr;
  235. {
  236.     return (i_ptr->ident & ID_STOREBOUGHT);
  237. }
  238.  
  239. /* Remove an automatically generated inscription.    -CJS- */
  240. static void 
  241. unsample(i_ptr)
  242. inven_type *i_ptr;
  243. {
  244.     int16 offset;
  245.     int8u indexx;
  246.  
  247. /* used to clear ID_DAMD flag, but I think it should remain set */
  248.     i_ptr->ident &= ~(ID_MAGIK | ID_EMPTY);
  249.     if ((offset = object_offset(i_ptr)) < 0)
  250.     return;
  251.     offset <<= 6;
  252.     indexx = i_ptr->subval & (ITEM_SINGLE_STACK_MIN - 1);
  253.     object_ident[offset + indexx] &= ~OD_TRIED;
  254. }
  255.  
  256. /* unquote() is no longer needed */
  257.  
  258. /* Somethings been sampled -CJS- */
  259. void 
  260. sample(i_ptr)
  261. inven_type *i_ptr;
  262. {
  263.     int16 offset;
  264.     int8u indexx;
  265.  
  266.     if ((offset = object_offset(i_ptr)) < 0)
  267.     return;
  268.     offset <<= 6;
  269.     indexx = i_ptr->subval & (ITEM_SINGLE_STACK_MIN - 1);
  270.     object_ident[offset + indexx] |= OD_TRIED;
  271. }
  272.  
  273. /* Somethings been identified                     */
  274. /*
  275.  * extra complexity by CJS so that it can merge store/dungeon objects when
  276.  * appropriate 
  277.  */
  278. void 
  279. identify(item)
  280. int *item;
  281. {
  282.     register int         i, x1, x2;
  283.     int                  j;
  284.     register inven_type *i_ptr, *t_ptr;
  285.  
  286.     i_ptr = &inventory[*item];
  287.  
  288.     if ((i_ptr->flags & TR_CURSED) && (i_ptr->tval != TV_MAGIC_BOOK) &&
  289.     (i_ptr->tval != TV_PRAYER_BOOK))
  290.     add_inscribe(i_ptr, ID_DAMD);
  291.  
  292.     if (!known1_p(i_ptr)) {
  293.     known1(i_ptr);
  294.     x1 = i_ptr->tval;
  295.     x2 = i_ptr->subval;
  296.     if (x2 < ITEM_SINGLE_STACK_MIN || x2 >= ITEM_GROUP_MIN)
  297.     /* no merging possible */
  298.         ;
  299.     else
  300.         for (i = 0; i < inven_ctr; i++) {
  301.         t_ptr = &inventory[i];
  302.         if (t_ptr->tval == x1 && t_ptr->subval == x2 && i != *item
  303.             && ((int)t_ptr->number + (int)i_ptr->number < 256)) {
  304.         /* make *item the smaller number */
  305.             if (*item > i) {
  306.             j = *item;
  307.             *item = i;
  308.             i = j;
  309.             }
  310.             msg_print("You combine similar objects from the shop and dungeon.");
  311.  
  312.             inventory[*item].number += inventory[i].number;
  313.             inven_ctr--;
  314.             for (j = i; j < inven_ctr; j++)
  315.             inventory[j] = inventory[j + 1];
  316.             invcopy(&inventory[j], OBJ_NOTHING);
  317.         }
  318.         }
  319.     }
  320. }
  321.  
  322. /*
  323.  * If an object has lost magical properties, remove the appropriate portion
  324.  * of the name.           -CJS- 
  325.  */
  326. void 
  327. unmagic_name(i_ptr)
  328. inven_type *i_ptr;
  329. {
  330.     i_ptr->name2 = SN_NULL;
  331. }
  332.  
  333.  
  334. /* defines for p1_use, determine how the p1 field is printed */
  335. #define IGNORED  0        /* never show (+x) */
  336. #define CHARGES  1        /* show p1 as charges */
  337. #define PLUSSES  2        /* show p1 as (+x) only */
  338. #define LIGHT    3        /* show p1 as turns of light */
  339. #define FLAGS    4        /* show p1 as (+x of yyy) */
  340. #define Z_PLUSSES 5             /* always show p1 as (+x), even if x==0 -CWS */
  341.  
  342.  
  343. /* Returns a description of item for inventory
  344.  * pref indicates that there should be an article added (prefix)
  345.  *
  346.  * note that since out_val can easily exceed 80 characters, objdes must
  347.  * always be called with a bigvtype as the first paramter 
  348.  *****
  349.  * Note that objdes now never returns a description ending with punctuation
  350.  * (ie, "."'s) -CWS 
  351.  */
  352.  
  353. void 
  354. objdes(out_val, i_ptr, pref)
  355. char                *out_val;
  356. register inven_type *i_ptr;
  357. int                  pref;
  358. {
  359. /* base name, modifier string */
  360.     register const char *basenm, *modstr;
  361.     bigvtype             tmp_val;
  362.     vtype                tmp_str, damstr;
  363.     int                  indexx, p1_use, modify, append_name;
  364.  
  365.     indexx = i_ptr->subval & (ITEM_SINGLE_STACK_MIN - 1);
  366.     basenm = object_list[i_ptr->index].name;
  367.     modstr = NULL;
  368.     damstr[0] = '\0';
  369.     p1_use = IGNORED;
  370.     modify = (known1_p(i_ptr) ? FALSE : TRUE);
  371.     append_name = FALSE;
  372.     switch (i_ptr->tval) {
  373.       case TV_MISC:
  374.       case TV_CHEST:
  375.     break;
  376.       case TV_SLING_AMMO:
  377.       case TV_BOLT:
  378.       case TV_ARROW:
  379.     (void)sprintf(damstr, " (%dd%d)", i_ptr->damage[0], i_ptr->damage[1]);
  380.     break;
  381.       case TV_LIGHT:
  382.     p1_use = LIGHT;
  383.     if (!stricmp("The Phial of Galadriel", basenm) && !known2_p(i_ptr))
  384.         basenm = "a Shining Phial";
  385.     if (!stricmp("The Star of Elendil", basenm) && !known2_p(i_ptr))
  386.         basenm = "a Shining Gem";
  387.     if (!stricmp("The Arkenstone of Thrain", basenm) && !known2_p(i_ptr))
  388.         basenm = "a Shining Gem";
  389.     break;
  390.       case TV_SPIKE:
  391.     break;
  392.       case TV_BOW:
  393.     switch(i_ptr->subval) { /* whole new code -CFT */
  394.       case 20: case 1: /* sling, sh. bow */
  395.         strcpy(damstr, " (x2)");
  396.         break;
  397.       case 21: case 2: case 10: /* sling of M, s bow of M, l bow, l xbow */
  398.         strcpy(damstr, " (x3)");
  399.         break;
  400.       case 3: case 11: /* l bow of M, l xbow of M, h xbow, BARD, CUBRAGOL */
  401.         strcpy(damstr, " (x4)");
  402.         break;
  403.       case 4: case 12:        /* h xbow of M, BELEG */
  404.         strcpy(damstr, " (x5)");
  405.         break;
  406.       default:        /* just in case... */
  407.         strcpy(damstr, " (unknown mult.)");
  408.     }
  409.     if (i_ptr->flags2 & TR_ARTIFACT)    /* only show p1 for artifacts... */
  410.         p1_use = FLAGS;
  411.     break;
  412.       case TV_HAFTED:
  413.       case TV_POLEARM:
  414.       case TV_SWORD:
  415.     (void)sprintf(damstr, " (%dd%d)", i_ptr->damage[0], i_ptr->damage[1]);
  416.     p1_use = FLAGS;
  417.     break;
  418.       case TV_DIGGING:
  419.     p1_use = Z_PLUSSES;
  420.     (void)sprintf(damstr, " (%dd%d)", i_ptr->damage[0], i_ptr->damage[1]);
  421.     break;
  422.       case TV_BOOTS:
  423.       case TV_GLOVES:
  424.       case TV_CLOAK:
  425.       case TV_HELM:
  426.       case TV_SHIELD:
  427.       case TV_HARD_ARMOR:
  428.       case TV_SOFT_ARMOR:
  429.     p1_use = FLAGS;
  430.     break;
  431.       case TV_AMULET:
  432.     p1_use = FLAGS;
  433.     if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  434.         basenm = "& %s Amulet";
  435.         modstr = amulets[indexx];
  436.         if (!modify)
  437.         append_name = TRUE;
  438.     } else {
  439.         basenm = "& Amulet";
  440.         append_name = TRUE;
  441.     }
  442.     break;
  443.       case TV_RING:
  444.     if (!stricmp("Power", basenm)) { /* name this "the One Ring" -CWS */
  445.         append_name = FALSE;
  446.         if (!known2_p(i_ptr))
  447.         basenm = "a plain gold Ring";
  448.         else
  449.         basenm = "The One Ring";
  450.     } else if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  451.         basenm = "& %s Ring";
  452.         modstr = rocks[indexx];
  453.         if (!modify)
  454.         append_name = TRUE;
  455.     } else {
  456.         basenm = "& Ring";
  457.         append_name = TRUE;
  458.     }
  459.     p1_use = PLUSSES;
  460.     break;
  461.       case TV_STAFF:
  462.     if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  463.         basenm = "& %s Staff";
  464.         modstr = woods[indexx];
  465.         if (!modify)
  466.         append_name = TRUE;
  467.     } else {
  468.         basenm = "& Staff";
  469.         append_name = TRUE;
  470.     }
  471.     p1_use = CHARGES;
  472.     break;
  473.       case TV_WAND:
  474.     if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  475.         basenm = "& %s Wand";
  476.         modstr = metals[indexx];
  477.         if (!modify)
  478.         append_name = TRUE;
  479.     } else {
  480.         basenm = "& Wand";
  481.         append_name = TRUE;
  482.     }
  483.     p1_use = CHARGES;
  484.     break;
  485.       case TV_ROD:
  486.     if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  487.         basenm = "& %s Rod";
  488.         modstr = metals[indexx];
  489.         if (!modify)
  490.         append_name = TRUE;
  491.     } else {
  492.         basenm = "& Rod";
  493.         append_name = TRUE;
  494.     }
  495.     break;
  496.       case TV_SCROLL1:
  497.       case TV_SCROLL2:
  498.     if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  499.         basenm = "& Scroll~ titled \"%s\"";
  500.         modstr = titles[indexx];
  501.         if (!modify)
  502.         append_name = TRUE;
  503.     } else {
  504.         basenm = "& Scroll~";
  505.         append_name = TRUE;
  506.     }
  507.     break;
  508.       case TV_POTION1:
  509.       case TV_POTION2:
  510.     if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  511.         basenm = "& %s Potion~";
  512.         modstr = colors[indexx];
  513.         if (!modify)
  514.         append_name = TRUE;
  515.     } else {
  516.         basenm = "& Potion~";
  517.         append_name = TRUE;
  518.     }
  519.     break;
  520.       case TV_FLASK:
  521.     break;
  522.       case TV_FOOD:
  523.     if (modify || !(plain_descriptions || store_bought_p(i_ptr))) {
  524.         if (!modify)
  525.         append_name = TRUE;
  526.         if (indexx <= 15)
  527.         basenm = "& %s Mushroom~";
  528.         else if (indexx <= 20)
  529.         basenm = "& Hairy %s Mold~";
  530.         else
  531.         append_name = FALSE;    /* Ordinary food has no name appended. */
  532.         if (indexx <= 20)
  533.         modstr = mushrooms[indexx];
  534.     } else {
  535.         append_name = TRUE;
  536.         if (indexx <= 15)
  537.         basenm = "& Mushroom~";
  538.         else if (indexx <= 20)
  539.         basenm = "& Hairy Mold~";
  540.         else
  541.         /* Ordinary food does not have a name appended.  */
  542.         append_name = FALSE;
  543.     }
  544.     break;
  545.       case TV_MAGIC_BOOK:
  546.     modstr = basenm;
  547.     basenm = "& Book~ of Magic Spells %s";
  548.     break;
  549.       case TV_PRAYER_BOOK:
  550.     modstr = basenm;
  551.     basenm = "& Holy Book~ of Prayers %s";
  552.     break;
  553.       case TV_OPEN_DOOR:
  554.       case TV_CLOSED_DOOR:
  555.       case TV_SECRET_DOOR:
  556.       case TV_RUBBLE:
  557.     break;
  558.       case TV_GOLD:
  559.       case TV_INVIS_TRAP:
  560.       case TV_VIS_TRAP:
  561.       case TV_UP_STAIR:
  562.       case TV_DOWN_STAIR:
  563.     (void)strcpy(out_val, object_list[i_ptr->index].name);
  564.     /* (void) strcat(out_val, "."); avoid ".." bug -CWS */
  565.     return;
  566.       case TV_STORE_DOOR:
  567.     (void)sprintf(out_val, "the entrance to the %s",
  568.               object_list[i_ptr->index].name);
  569.     return;
  570.       default:
  571.     (void)strcpy(out_val, "Error in objdes()");
  572.     return;
  573.     }
  574.     if (modstr != NULL)
  575.     (void)sprintf(tmp_val, basenm, modstr);
  576.     else
  577.     (void)strcpy(tmp_val, basenm);
  578.     if (append_name) {
  579.     (void)strcat(tmp_val, " of ");
  580.     (void)strcat(tmp_val, object_list[i_ptr->index].name);
  581.     }
  582.     if (i_ptr->number != 1) {
  583.     insert_str(tmp_val, "ch~", "ches");
  584.     insert_str(tmp_val, "~", "s");
  585.     } else
  586.     insert_str(tmp_val, "~", NULL);
  587.     if (!pref) {
  588.     if (!strncmp("some", tmp_val, 4))
  589.         (void)strcpy(out_val, &tmp_val[5]);
  590.     else if (tmp_val[0] == '&')
  591.     /* eliminate the '& ' at the beginning */
  592.         (void)strcpy(out_val, &tmp_val[2]);
  593.     else
  594.         (void)strcpy(out_val, tmp_val);
  595.     } else {
  596.     if (i_ptr->name2 != SN_NULL && known2_p(i_ptr)) {
  597.         (void)strcat(tmp_val, " ");
  598.         (void)strcat(tmp_val, special_names[i_ptr->name2]);
  599.     }
  600.     if (damstr[0] != '\0')
  601.         (void)strcat(tmp_val, damstr);
  602.     if (known2_p(i_ptr)) {
  603.     /* originally used %+d, but several machines don't support it */
  604.         if (i_ptr->ident & ID_SHOW_HITDAM)
  605.         (void)sprintf(tmp_str, " (%c%d,%c%d)",
  606.               (i_ptr->tohit < 0) ? '-' : '+', MY_ABS( i_ptr->tohit),
  607.              (i_ptr->todam < 0) ? '-' : '+', MY_ABS(i_ptr->todam));
  608.         else if (i_ptr->tohit != 0)
  609.         (void)sprintf(tmp_str, " (%c%d)",
  610.              (i_ptr->tohit < 0) ? '-' : '+', MY_ABS(i_ptr->tohit));
  611.         else if (i_ptr->todam != 0)
  612.         (void)sprintf(tmp_str, " (%c%d)",
  613.              (i_ptr->todam < 0) ? '-' : '+', MY_ABS(i_ptr->todam));
  614.         else
  615.         tmp_str[0] = '\0';
  616.         (void)strcat(tmp_val, tmp_str);
  617.     }
  618.     /* Crowns have a zero base AC, so make a special test for them. */
  619.     if (i_ptr->ac != 0 || (i_ptr->tval == TV_HELM)) {
  620.         (void)sprintf(tmp_str, " [%d", i_ptr->ac);
  621.         (void)strcat(tmp_val, tmp_str);
  622.         if (known2_p(i_ptr)) {
  623.         /* originally used %+d, but several machines don't support it */
  624.         (void)sprintf(tmp_str, ",%c%d",
  625.                (i_ptr->toac < 0) ? '-' : '+', MY_ABS(i_ptr->toac));
  626.         (void)strcat(tmp_val, tmp_str);
  627.         }
  628.         (void)strcat(tmp_val, "]");
  629.     } else if ((i_ptr->toac != 0) && known2_p(i_ptr)) {
  630.     /* originally used %+d, but several machines don't support it */
  631.         (void)sprintf(tmp_str, " [%c%d]",
  632.               (i_ptr->toac < 0) ? '-' : '+', MY_ABS(i_ptr->toac));
  633.         (void)strcat(tmp_val, tmp_str);
  634.     }
  635.  
  636.     tmp_str[0] = '\0';
  637.  
  638.     /* override defaults, check for p1 flags in the ident field */
  639.     if (p1_use != IGNORED) {
  640.         if (p1_use == LIGHT);
  641.         else if (i_ptr->ident & ID_NOSHOW_P1)
  642.         p1_use = IGNORED;
  643.         else if (i_ptr->ident & ID_NOSHOW_TYPE)
  644.         p1_use = PLUSSES;
  645.     }
  646.  
  647.     if (p1_use == IGNORED);
  648.     else if ((p1_use == LIGHT) && !(i_ptr->flags2 & TR_ARTIFACT))
  649.         (void)sprintf(tmp_str, " with %d turns of light", i_ptr->p1);
  650.  
  651.     else if (known2_p(i_ptr)) {
  652.  
  653.         if (p1_use == CHARGES)
  654.         (void)sprintf(tmp_str, " (%d charge%s", i_ptr->p1,
  655.                   (i_ptr->p1 == 1 ? ")" : "s)"));
  656.  
  657.         else if (p1_use == Z_PLUSSES) /* (+0) digging implements -CWS */
  658.             (void)sprintf(tmp_str, " (%c%d)",
  659.                   (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  660.  
  661.         else if (i_ptr->p1 != 0) {
  662.         if (p1_use == PLUSSES)
  663.             (void)sprintf(tmp_str, " (%c%d)",
  664.                   (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  665.         else if (i_ptr->ident & ID_NOSHOW_TYPE)
  666.             (void)sprintf(tmp_str, " (%c%d)",
  667.                   (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  668.  
  669.         else if (p1_use == FLAGS) {
  670.             if ((i_ptr->flags & TR_SPEED) &&
  671.                  (i_ptr->name2 != SN_SPEED))
  672.             (void)sprintf(tmp_str, " (%c%d to speed)",
  673.                       (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  674.             else if (i_ptr->flags & TR_SEARCH)
  675.             /*            && (i_ptr->name2 != SN_SEARCH)) */
  676.             (void)sprintf(tmp_str, " (%c%d to searching)",
  677.                       (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  678.             else if ((i_ptr->flags & TR_STEALTH) &&
  679.                  (i_ptr->name2 != SN_STEALTH))
  680.             (void)sprintf(tmp_str, " (%c%d to stealth)",
  681.                       (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  682.             else if ((i_ptr->flags & TR_INFRA) &&
  683.                  (i_ptr->name2 != SN_INFRAVISION))
  684.             (void)sprintf(tmp_str, " (%c%d to infravision)",
  685.                       (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  686.             else if (i_ptr->flags2 & TR_ATTACK_SPD) {
  687.             if (MY_ABS(i_ptr->p1) == 1)
  688.                 (void)sprintf(tmp_str, " (%c%d attack)",
  689.                       (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  690.             else
  691.                 (void)sprintf(tmp_str, " (%c%d attacks)",
  692.                       (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  693.             } /* attack speed */
  694.             else
  695.             (void)sprintf(tmp_str, " (%c%d)",
  696.                       (i_ptr->p1 < 0) ? '-' : '+', MY_ABS(i_ptr->p1));
  697.         }     /* p1_use == FLAGS */
  698.         }         /* p1 != 0 */
  699.     }             /* if known2_p (fully identified) */
  700.  
  701.     (void)strcat(tmp_val, tmp_str);
  702.  
  703.     /* ampersand is always the first character */
  704.     if (tmp_val[0] == '&') {
  705.     /* use &tmp_val[1], so that & does not appear in output */
  706.         if (i_ptr->number > 1)
  707.         (void)sprintf(out_val, "%d%s", (int)i_ptr->number, &tmp_val[1]);
  708.         else if (i_ptr->number < 1)
  709.         (void)sprintf(out_val, "%s%s", "no more", &tmp_val[1]);
  710.         else if (known2_p(i_ptr) && (i_ptr->tval >= TV_MIN_WEAR)
  711.              && (i_ptr->tval <= TV_MAX_WEAR) &&
  712.              (i_ptr->flags2 & TR_ARTIFACT))
  713.         (void)sprintf(out_val, "The%s", &tmp_val[1]);
  714.         else if (is_a_vowel(tmp_val[2]))
  715.         (void)sprintf(out_val, "an%s", &tmp_val[1]);
  716.         else
  717.         (void)sprintf(out_val, "a%s", &tmp_val[1]);
  718.     }
  719.     /* handle 'no more' case specially */
  720.     else if (i_ptr->number < 1) {
  721.     /* check for "some" at start */
  722.         if (!strncmp("some", tmp_val, 4))
  723.         (void)sprintf(out_val, "no more %s", &tmp_val[5]);
  724.     /* here if no article */
  725.         else
  726.         (void)sprintf(out_val, "no more %s", tmp_val);
  727.     } else
  728.         (void)strcpy(out_val, tmp_val);
  729.  
  730.     tmp_str[0] = '\0';
  731.     if ((indexx = object_offset(i_ptr)) >= 0) {
  732.         indexx = (indexx <<= 6) +
  733.         (i_ptr->subval & (ITEM_SINGLE_STACK_MIN - 1));
  734.     /* don't print tried string for store bought items */
  735.         if ((object_ident[indexx] & OD_TRIED) && !store_bought_p(i_ptr))
  736.         (void)strcat(tmp_str, "tried ");
  737.     }
  738.     if ((i_ptr->ident & (ID_MAGIK | ID_EMPTY | ID_DAMD)) &&
  739.         i_ptr->tval != TV_MAGIC_BOOK && i_ptr->tval != TV_PRAYER_BOOK) {
  740.         if (i_ptr->ident & ID_MAGIK)
  741.         (void)strcat(tmp_str, "blessed ");
  742.         if (i_ptr->ident & ID_EMPTY)
  743.         (void)strcat(tmp_str, "empty ");
  744.         if (i_ptr->ident & ID_DAMD)
  745.         (void)strcat(tmp_str, "cursed ");
  746.     }
  747.     if ((known2_p(i_ptr) || store_bought_p(i_ptr)) &&
  748.         ((!strncmp(i_ptr->inscrip, "average", 7)) ||
  749.          (!strncmp(i_ptr->inscrip, "good", 4)) ||
  750.          (!strncmp(i_ptr->inscrip, "excellent", 9)) ||
  751.          (!strncmp(i_ptr->inscrip, "special", 7))))
  752.         i_ptr->inscrip[0] = '\0';
  753.     if (i_ptr->inscrip[0] != '\0')
  754.         (void)strcat(tmp_str, i_ptr->inscrip);
  755.     else if ((indexx = strlen(tmp_str)) > 0)
  756.     /* remove the extra blank at the end */
  757.         tmp_str[indexx - 1] = '\0';
  758.     if (tmp_str[0]) {
  759.         (void)sprintf(tmp_val, " {%s}", tmp_str);
  760.         (void)strcat(out_val, tmp_val);
  761.     }
  762.     /* (void) strcat(out_val, "."); avoid ".." bug -CWS */
  763.     }
  764. }
  765.  
  766. void 
  767. invcopy(to, from_index)
  768. register inven_type *to;
  769. int                  from_index;
  770. {
  771.     register treasure_type *from;
  772.  
  773.     from = &object_list[from_index];
  774.     to->index = from_index;
  775.     to->name2 = SN_NULL;
  776.     to->inscrip[0] = '\0';
  777.     to->flags = from->flags;
  778.     to->flags2 = from->flags2;
  779.     to->tval = from->tval;
  780.     to->tchar = from->tchar;
  781.     to->p1 = from->p1;
  782.     to->cost = from->cost;
  783.     to->subval = from->subval;
  784.     to->number = from->number;
  785.     to->weight = from->weight;
  786.     to->tohit = from->tohit;
  787.     to->todam = from->todam;
  788.     to->ac = from->ac;
  789.     to->toac = from->toac;
  790.     to->damage[0] = from->damage[0];
  791.     to->damage[1] = from->damage[1];
  792.     to->level = from->level;
  793.     to->ident = 0;
  794. }
  795.  
  796.  
  797. /* Describe number of remaining charges.        -RAK-     */
  798. void 
  799. desc_charges(item_val)
  800. int item_val;
  801. {
  802.     register int rem_num;
  803.     vtype        out_val;
  804.  
  805.     if (known2_p(&inventory[item_val])) {
  806.     rem_num = inventory[item_val].p1;
  807.     (void)sprintf(out_val, "You have %d charges remaining.", rem_num);
  808.     msg_print(out_val);
  809.     }
  810. }
  811.  
  812.  
  813. /* Describe amount of item remaining.            -RAK-     */
  814. void 
  815. desc_remain(item_val)
  816. int item_val;
  817. {
  818.     bigvtype             out_val, tmp_str;
  819.     register inven_type *i_ptr;
  820.  
  821.     i_ptr = &inventory[item_val];
  822.     i_ptr->number--;
  823.     objdes(tmp_str, i_ptr, TRUE);
  824.     i_ptr->number++;
  825.     (void)sprintf(out_val, "You have %s.", tmp_str);
  826.     msg_print(out_val);
  827. }
  828.